package top.whysu.edevice.service.manage.impl;

import com.alibaba.fastjson.JSON;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import top.whysu.edevice.constant.CodeConstant;
import top.whysu.edevice.dao.manage.ManageSecretKeyDao;
import top.whysu.edevice.dao.manage.ManageVoucherDao;
import top.whysu.edevice.dto.ezviz.token.TokenRequestDTO;
import top.whysu.edevice.dto.ezviz.token.TokenResponseDTO;
import top.whysu.edevice.dto.manage.SecretKeyAddModifyDTO;
import top.whysu.edevice.dto.manage.SecretKeyNameDTO;
import top.whysu.edevice.dto.manage.SecretKeyPageDTO;
import top.whysu.edevice.dto.manage.SecretKeyQueryDTO;
import top.whysu.edevice.dto.page.PagenationDataDTO;
import top.whysu.edevice.exception.BusinessException;
import top.whysu.edevice.po.manage.ManageSecretKeyPO;
import top.whysu.edevice.po.manage.ManageVoucherPO;
import top.whysu.edevice.service.ezviz.EzvizHttpService;
import top.whysu.edevice.service.manage.ManageSecretKeyService;
import top.whysu.edevice.service.manage.ManageVoucherService;
import top.whysu.edevice.service.relative.RelativeSecretKeyTokenService;
import top.whysu.edevice.service.system.AccountService;
import top.whysu.edevice.utils.PageUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

@Service("ManageSecretKeyServiceImpl")
public class ManageSecretKeyServiceImpl implements ManageSecretKeyService {
    private static Logger LOGGER = LoggerFactory.getLogger(ManageSecretKeyServiceImpl.class);

    @Resource
    private ManageVoucherService manageVoucherService;
    @Resource
    private ManageVoucherDao manageVoucherDao;
    @Resource
    private ManageSecretKeyDao manageSecretKeyDao;
    @Resource
    private AccountService accountService;
    @Resource
    private EzvizHttpService ezvizHttpService;
    @Resource
    private RelativeSecretKeyTokenService relativeSecretKeyTokenService;

    @Override
    public BigDecimal wholeAddModify(SecretKeyAddModifyDTO addModifyDTO) {
        // 当前只允许添加一个秘钥
        onlyOneSecretKey(addModifyDTO);
        // 主键id
        BigDecimal id = addModifyDTO.getId();
        // 验证凭证组是否存在
        ManageVoucherPO manageVoucherPO = manageVoucherDao.queryById(addModifyDTO.getVoucherId());
        if (manageVoucherPO == null) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "凭证组不存在！请刷新界面后再重试！");
        }
        // 校验秘钥名称唯一性
        validateSecretName(addModifyDTO.getVoucherId(), addModifyDTO.getSecretKeyName(), id);
        // 获取accessToken
        TokenRequestDTO accessTokenRequestDTO = new TokenRequestDTO();
        accessTokenRequestDTO.setAppKey(addModifyDTO.getAppKey());
        accessTokenRequestDTO.setAppSecret(addModifyDTO.getAppSecret());
        TokenResponseDTO responseDTO = ezvizHttpService.getAccessToken(accessTokenRequestDTO);
        if (responseDTO == null) {
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "获取accessToken失败！");
        }
        // 当前操作用户
        String currentUser = accountService.getCurrentLoginUser();
        if (id != null) {
            // 编辑
            ManageSecretKeyPO po = new ManageSecretKeyPO();
            BeanUtils.copyProperties(addModifyDTO, po);
            po.setUpdateTime(new Date());
            po.setUpdateBy(currentUser);
            manageSecretKeyDao.update(po);
        } else {
            // 新增
            ManageSecretKeyPO po = new ManageSecretKeyPO();
            BeanUtils.copyProperties(addModifyDTO, po);
            po.setCreateTime(new Date());
            po.setUpdateTime(new Date());
            po.setCreateBy(currentUser);
            po.setUpdateBy(currentUser);
            manageSecretKeyDao.insert(po);
            id = po.getId();
        }
        // 处理秘钥-token关联关系
        relativeSecretKeyTokenService.wholeSecretKeyToken(id, responseDTO.getAccessToken(), responseDTO.getExpireTime());
        return id;
    }

    @Override
    public PagenationDataDTO<SecretKeyPageDTO> selectPage(SecretKeyQueryDTO secretKeyQueryDTO) {
        // 获取集合
        LinkedHashMap queryMap = JSON.parseObject(JSON.toJSONString(secretKeyQueryDTO), LinkedHashMap.class);
        // limit的起始值
        queryMap.put("rowIndex", PageUtils.getRowIndex(secretKeyQueryDTO.getPageNum(), secretKeyQueryDTO.getPageSize()));
        List<SecretKeyPageDTO> list = manageSecretKeyDao.queryAllByLimit(queryMap);
        // 获取总数
        long totalSize = manageSecretKeyDao.count(queryMap);
        if (CollectionUtils.isNotEmpty(list) && totalSize > 0) {
            return new PagenationDataDTO<>(totalSize, secretKeyQueryDTO.getPageNum(), secretKeyQueryDTO.getPageSize(), list);
        } else {
            return PageUtils.toPagedResult(null);
        }
    }

    @Override
    public void delete(BigDecimal id) {
        if (id == null) {
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "参数错误！id不能为空！");
        }
        manageSecretKeyDao.deleteById(id);
    }

    @Override
    public List<SecretKeyNameDTO> getSecretKeyListByVoucherTreeId(BigDecimal voucherTreeId) {
        if (voucherTreeId == null) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "凭证组的树节点id不能为空！");
        }
        // 根据树结构id查询凭证组信息
        ManageVoucherPO manageVoucherPO = manageVoucherService.getVoucherByTreeId(voucherTreeId);
        if (manageVoucherPO == null) {
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "凭证组不存在！请刷新界面后重试！");
        }
        // 查询该凭证组下的所有秘钥
        return manageSecretKeyDao.selectSecretKeyListByVoucherId(manageVoucherPO.getId());
    }

    @Override
    public List<SecretKeyNameDTO> getSecretKeyListByVoucherId(BigDecimal voucherId) {
        if (voucherId == null) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "凭证组id不能为空！");
        }
        // 查询该凭证组下的所有秘钥
        return manageSecretKeyDao.selectSecretKeyListByVoucherId(voucherId);
    }

    /**
     * 验证名称在当前凭证组下是否已经存在
     *
     * @param voucherId  凭证组id
     * @param secretName 秘钥名称
     * @param id         秘钥主键id
     */
    private void validateSecretName(BigDecimal voucherId, String secretName, BigDecimal id) {
        // 查询当前凭证组下的秘钥名称是否重复
        ManageSecretKeyPO queryPO = new ManageSecretKeyPO();
        queryPO.setVoucherId(voucherId);
        queryPO.setSecretKeyName(secretName);
        List<ManageSecretKeyPO> secretKeyPOList = manageSecretKeyDao.queryAll(queryPO);
        if (CollectionUtils.isNotEmpty(secretKeyPOList)) {
            secretKeyPOList.forEach(it -> {
                if (id == null) {
                    // 新增
                    throw new BusinessException(CodeConstant.Http.INFO_ERROR, "当前凭证组下已存在相同名称的秘钥！");
                } else {
                    // 编辑
                    if (!id.equals(it.getId())) {
                        throw new BusinessException(CodeConstant.Http.INFO_ERROR, "当前凭证组下已存在相同名称的秘钥！");
                    }
                }
            });
        }
    }

    /**
     * 当前只允许添加一个秘钥
     */
    private void onlyOneSecretKey(SecretKeyAddModifyDTO addModifyDTO) {
        if (addModifyDTO.getId() == null) {
            // 新增
            long count = manageSecretKeyDao.count(new HashMap());
            if (count >= 1) {
                throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "当前系统只允许添加一个秘钥！");
            }
        }
    }
}
